package org.dromara.crawler.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dtflys.forest.Forest;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestRequestType;
import com.dtflys.forest.http.ForestResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.crawler.config.AnalysisAlgorithmProperties;
import org.dromara.crawler.config.CrawlerAlgorithmProperties;
import org.dromara.crawler.domain.bo.GraphHandleBo;
import org.dromara.crawler.domain.vo.ElementEventVo;
import org.dromara.crawler.mongo.mongoservice.ElementEventService;
import org.dromara.crawler.service.FileForwardClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 算法调用接口
 *
 * @author Shup
 * @date 2025/7/23 17:14
 */

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/algorithmApi")
public class AlgorithmApiController {

    private final FileForwardClient fileForwardClient;

    private final CrawlerAlgorithmProperties crawlerAlgorithmProperties;
    private final AnalysisAlgorithmProperties analysisAlgorithmProperties;
    private final ElementEventService elementEventService;

    /**
     * 查询热点词云接口
     */
    @GetMapping("/gethotspot")
    public R<JSONArray> gethotspot(@RequestParam(required = false) String keyword) {
        ForestRequest forestRequest = Forest.request();
        if (ObjectUtil.isNotEmpty(keyword)) {
            Map<String, Object> map = Map.of("keyword", keyword);
            forestRequest.addQuery(map);
        }
        forestRequest.setUrl(crawlerAlgorithmProperties.getHostUrl() + crawlerAlgorithmProperties.getHotspotApi());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            JSONObject jsonObject = JSONUtil.parseObj(response.getContent());
            return R.ok(jsonObject.getJSONArray("data"));
        }
        return R.fail("调用失败,请检查算法服务");
    }

    /**
     * 查询文本自动标注接口
     */
    @PostMapping("/getTextLabel")
    public R<JSONObject> getTextLabel(@RequestBody String text) {
        ForestRequest forestRequest = Forest.request();
        if (ObjectUtil.isNotEmpty(text)) {
            Map<String, Object> map = Map.of("text", text);
            forestRequest.addBody(map);
        }
        forestRequest.setContentType("application/json");
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setUrl(crawlerAlgorithmProperties.getHostUrl() + crawlerAlgorithmProperties.getTextLabelApi());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            JSONObject jsonObject = JSONUtil.parseObj(response.getContent());
            return R.ok(jsonObject);
        }
        return R.fail("调用失败,请检查算法服务");
    }


    /**
     * 查询画像分析接口
     */
    @GetMapping("/getImageAnalysis")
    public R<JSONObject> getImageAnalysis(@RequestParam String targetId) {
        if(ObjectUtil.isEmpty(targetId)){
            return R.fail("目标ID为空");
        }
        ForestRequest forestRequest = Forest.request();
        Map<String, Object> map = Map.of("mongo_id", targetId);
        forestRequest.addBody(map);
        forestRequest.setContentType("application/json");
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setUrl(analysisAlgorithmProperties.getHostUrl() + analysisAlgorithmProperties.getEventAnalyzePower());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            JSONObject jsonObject = JSONUtil.parseObj(response.getContent());
            return R.ok(jsonObject);
        }
        return R.fail("调用失败,请检查算法服务");
    }


    /**
     * 查询演化分析接口
     */
    @GetMapping("/getEvo")
    public R<Object> getEvo(@RequestParam String eventId) {
        ForestRequest forestRequest = Forest.request();
        Map<String, Object> map = Map.of("event_id", eventId);
        //Map<String, Object> map = Map.of("event_id", "Th_POL-00017");
        forestRequest.addBody(map);
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setContentType("application/json");
        forestRequest.setUrl(analysisAlgorithmProperties.getHostUrl() + analysisAlgorithmProperties.getEvo());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            String content = response.getContent();
            if(JSONUtil.isTypeJSONObject(content)){
                JSONObject jsonObject = JSONUtil.parseObj(content);
                return R.ok(jsonObject);
            }else if(JSONUtil.isTypeJSONArray(content)){
                JSONArray jsonArray = JSONUtil.parseArray(content);
                Map<String, Map<String, Object>> idsWithCoordinateMap = new HashMap<>();
                List<String> eventIds = new ArrayList<>();
                extractIdsAndAddCoordinate(jsonArray, eventIds, idsWithCoordinateMap);
                List<ElementEventVo> list = elementEventService.queryEventByEventIds(eventIds);
                updateCoordinateFromList(list, idsWithCoordinateMap);
                updateCoordinateInData(jsonArray, idsWithCoordinateMap);
                return R.ok(jsonArray);
            }
        }
        return R.fail("调用失败,请检查算法服务");
    }

    /**
     * 查询预测分析接口
     */
    @GetMapping("/getPred")
    public R<Object> getPred(@RequestParam String eventId) {
        ForestRequest forestRequest = Forest.request();
        //Map<String, Object> map = Map.of("event_id", "Th_POL-00017");
        Map<String, Object> map = Map.of("event_id", eventId);
        forestRequest.addBody(map);
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setContentType("application/json");
        forestRequest.setUrl(analysisAlgorithmProperties.getHostUrl() + analysisAlgorithmProperties.getPred());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            String content = response.getContent();
            if(JSONUtil.isTypeJSONObject(content)){
                JSONObject jsonObject = JSONUtil.parseObj(content);
                return R.ok(jsonObject);
            }else if(JSONUtil.isTypeJSONArray(content)){
                JSONArray jsonArray = JSONUtil.parseArray(content);
                return R.ok(jsonArray);
            }
        }
        return R.fail("调用失败,请检查算法服务");
    }

    /**
     * 关联度筛选阈值设置接口
     */
    @GetMapping("/setRelationFilter")
    public R<Object> setRelationFilter(@RequestParam Integer threshold) {
        ForestRequest forestRequest = Forest.request();
        Map<String, Object> map = Map.of("threshold", threshold);
        forestRequest.addBody(map);
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setContentType("application/json");
        forestRequest.setUrl(analysisAlgorithmProperties.getHostUrl() + analysisAlgorithmProperties.getRelationFilter());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            String content = response.getContent();
            CacheUtils.put(CacheNames.relationFilter,"threshold" ,threshold);
            if(JSONUtil.isTypeJSONObject(content)){
                JSONObject jsonObject = JSONUtil.parseObj(content);
                return R.ok(jsonObject);
            }else if(JSONUtil.isTypeJSONArray(content)){
                JSONArray jsonArray = JSONUtil.parseArray(content);
                return R.ok(jsonArray);
            }
        }
        return R.fail("调用失败,请检查算法服务");
    }

    /**
     * 关联度筛选阈值查询接口
     */
    @GetMapping("/getRelationFilter")
    public R<Object> getRelationFilter() {
        Integer threshold = CacheUtils.get(CacheNames.relationFilter,"threshold");
        return R.ok(threshold);
    }

    // 递归提取所有的id，并为每个节点添加coordinate字段到Map
    private void extractIdsAndAddCoordinate(JSONArray jsonArray, List<String> eventIds, Map<String, Map<String, Object>> idsWithCoordinateMap) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String id = jsonObject.getStr("id");
            eventIds.add(id);

            // 新增coordinate字段，初始化为空
            String coordinate = "";  // 根据实际需要填充coordinate字段

            // 将id和coordinate存入Map，key为id
            Map<String, Object> idCoordinateMap = new HashMap<>();
            idCoordinateMap.put("id", id);
            idCoordinateMap.put("coordinate", coordinate);
            idsWithCoordinateMap.put(id, idCoordinateMap);

            // 递归处理子节点
            if (jsonObject.containsKey("children")) {
                JSONArray children = jsonObject.getJSONArray("children");
                extractIdsAndAddCoordinate(children, eventIds, idsWithCoordinateMap);
            }
        }
    }

    // 根据list中的元素更新idsWithCoordinateMap中的coordinate字段
    private void updateCoordinateFromList(List<ElementEventVo> list, Map<String, Map<String, Object>> idsWithCoordinateMap) {
        // 遍历list中的元素
        for (ElementEventVo event : list) {
            String eventId = event.getEventId(); // 获取ElementEventVo中的ID
            String coordinate = event.getSpacePositionCoordinate(); // 获取ElementEventVo中的coordinate

            // 通过eventId直接在Map中查找并更新对应的coordinate值
            Map<String, Object> idCoordinateMap = idsWithCoordinateMap.get(eventId);
            if (idCoordinateMap != null) {
                idCoordinateMap.put("coordinate", coordinate);
            }
        }
    }

    // 更新jsonArray中的coordinate字段
    private void updateCoordinateInData(JSONArray jsonArray, Map<String, Map<String, Object>> idsWithCoordinateMap) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String id = jsonObject.getStr("id");

            // 从Map中查找对应的coordinate，并更新到jsonObject中
            Map<String, Object> idCoordinateMap = idsWithCoordinateMap.get(id);
            if (idCoordinateMap != null) {
                // 更新coordinate字段
                jsonObject.set("coordinate", idCoordinateMap.get("coordinate"));
            }

            // 递归更新子节点
            if (jsonObject.containsKey("children")) {
                JSONArray children = jsonObject.getJSONArray("children");
                updateCoordinateInData(children, idsWithCoordinateMap);
            }
        }
    }

    /**
     * 图谱补全接口
     */
    @PostMapping("/graphCompletion")
    public R<Object> graphCompletion(@RequestBody JSONObject data) {
        ForestRequest forestRequest = Forest.request();
        forestRequest.addBody(data);
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setContentType("application/json");
        forestRequest.setUrl(crawlerAlgorithmProperties.getHostUrl() + crawlerAlgorithmProperties.getGraphCompletionApi());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            String content = response.getContent();
            if(JSONUtil.isTypeJSONObject(content)){
                JSONObject jsonObject = JSONUtil.parseObj(content);
                return R.ok(jsonObject);
            }else if(JSONUtil.isTypeJSONArray(content)){
                JSONArray jsonArray = JSONUtil.parseArray(content);
                return R.ok(jsonArray);
            }
        }
        return R.fail("调用失败,请检查算法服务");
    }

    /**
     * 图谱纠错接口
     */
    @PostMapping("/graphCorrection")
    public R<Object> graphCorrection(@RequestBody JSONObject data) {
        ForestRequest forestRequest = Forest.request();
        forestRequest.addBody(data);
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setContentType("application/json");
        forestRequest.setUrl(crawlerAlgorithmProperties.getHostUrl() + crawlerAlgorithmProperties.getGraphCorrectionApi());
        ForestResponse response = forestRequest.executeAsResponse();
        if (response.isSuccess()) {
            String content = response.getContent();
            if(JSONUtil.isTypeJSONObject(content)){
                JSONObject jsonObject = JSONUtil.parseObj(content);
                return R.ok(jsonObject);
            }else if(JSONUtil.isTypeJSONArray(content)){
                JSONArray jsonArray = JSONUtil.parseArray(content);
                return R.ok(jsonArray);
            }
        }
        return R.fail("调用失败,请检查算法服务");
    }


    /**
     * 图文语义接口
     */
    @PostMapping("/imagesAnalyze")
    public R<Object> imagesAnalyze( @RequestParam("images") List<MultipartFile> images,
                                    @RequestParam("text") String text) {
        ForestRequest forestRequest = Forest.request();
        forestRequest.setType(ForestRequestType.POST);
        forestRequest.setUrl(crawlerAlgorithmProperties.getHostUrl() + crawlerAlgorithmProperties.getImageAnalyze());
        forestRequest.contentType("multipart/form-data");
        for(int i=0;i<images.size();i++){
            try {
                MultipartFile multipartFile = images.get(i);
                forestRequest.addFile("images",multipartFile.getBytes(), multipartFile.getOriginalFilename());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        forestRequest.addBody("text", text);
        ForestResponse response = forestRequest.executeAsResponse();
        if(response.isSuccess()){
            return R.ok(JSONUtil.parseObj(response.getContent()));
        }else {
            return R.fail("调用失败,请检查算法服务");
        }
    }



}
